home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / access / index / indexam.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  13.6 KB  |  536 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    indexam.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    general index access method routines
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *    index_open     - open an index relation by relationId
  10.  *    index_openr     - open a index relation by name
  11.  *    index_close     - close a index relation
  12.  *    index_beginscan - start a scan of an index
  13.  *    index_rescan      - restart a scan of an index
  14.  *    index_endscan     - end a scan
  15.  *    index_insert     - insert an index tuple into a relation
  16.  *    index_delete     - delete an item from an index relation
  17.  *    index_markpos      - mark a scan position
  18.  *    index_restrpos  - restore a scan position
  19.  *    index_getnext     - get the next tuple from a scan
  20.  * **    index_fetch    - retrieve tuple with tid
  21.  * **    index_replace    - replace a tuple
  22.  * **    index_getattr    - get an attribute from an index tuple
  23.  *    index_getprocid - get a support procedure id from the rel tuple
  24.  *    
  25.  *    IndexScanIsValid - check index scan
  26.  *
  27.  *   NOTES
  28.  *    This file contains the index_ routines which used
  29.  *    to be a scattered collection of stuff in access/genam.
  30.  *
  31.  *    The ** routines: index_fetch, index_replace, and index_getattr
  32.  *    have not yet been implemented.  They may not be needed.
  33.  *
  34.  * old comments
  35.  *     Scans are implemented as follows:
  36.  *
  37.  *     `0' represents an invalid item pointer.
  38.  *     `-' represents an unknown item pointer.
  39.  *     `X' represents a known item pointers.
  40.  *     `+' represents known or invalid item pointers.
  41.  *     `*' represents any item pointers.
  42.  *
  43.  *     State is represented by a triple of these symbols in the order of
  44.  *     previous, current, next.  Note that the case of reverse scans works
  45.  *     identically.
  46.  *
  47.  *        State    Result
  48.  *     (1)    + + -    + 0 0        (if the next item pointer is invalid)
  49.  *     (2)        + X -        (otherwise)
  50.  *     (3)    * 0 0    * 0 0        (no change)
  51.  *     (4)    + X 0    X 0 0        (shift)
  52.  *     (5)    * + X    + X -        (shift, add unknown)
  53.  *
  54.  *     All other states cannot occur.
  55.  *
  56.  *     Note: It would be possible to cache the status of the previous and
  57.  *          next item pointer using the flags.
  58.  *
  59.  *  IDENTIFICATION
  60.  *    $Header: /private/postgres/src/access/index/RCS/indexam.c,v 1.15 1992/04/13 18:30:47 mer Exp $
  61.  * ----------------------------------------------------------------
  62.  */
  63.  
  64. #include "tmp/postgres.h"
  65.  
  66. #include "access/attnum.h"
  67. #include "access/genam.h"
  68. #include "access/heapam.h"
  69. #include "access/itup.h"
  70. #include "access/newam.h"
  71. #include "access/relscan.h"
  72. #include "access/sdir.h"
  73. #include "access/skey.h"
  74. #include "access/funcindex.h"
  75.  
  76. #include "storage/form.h"
  77. #include "utils/log.h"
  78. #include "utils/rel.h"
  79.  
  80. #include "catalog/catname.h"
  81. #include "catalog/pg_attribute.h"
  82. #include "catalog/pg_index.h"
  83. #include "catalog/pg_proc.h"
  84.  
  85. RcsId("$Header: /private/postgres/src/access/index/RCS/indexam.c,v 1.15 1992/04/13 18:30:47 mer Exp $");
  86.  
  87. /* ----------------
  88.  *   undefine macros we aren't going to use that would otherwise
  89.  *   get in our way..  delete is defined in c.h and the am's are
  90.  *   defined in heapam.h
  91.  * ----------------
  92.  */
  93. #undef delete
  94. #undef aminsert
  95. #undef amdelete
  96. #undef ambeginscan
  97. #undef amrescan
  98. #undef amendscan
  99. #undef ammarkpos
  100. #undef amrestrpos
  101. #undef amgettuple
  102.  
  103. /* ----------------------------------------------------------------
  104.  *            macros used in index_ routines
  105.  * ----------------------------------------------------------------
  106.  */
  107. #define RELATION_CHECKS \
  108.     Assert(RelationIsValid(relation)); \
  109.     Assert(FormIsValid((Form) relation->rd_am))
  110.  
  111. #define SCAN_CHECKS \
  112.     Assert(IndexScanIsValid(scan)); \
  113.     Assert(RelationIsValid(scan->relation)); \
  114.     Assert(FormIsValid((Form) scan->relation->rd_am))
  115.  
  116. #define GET_REL_PROCEDURE(x,y) \
  117.     CppConcat(procedure = relation->rd_am->,y); \
  118.     if (! RegProcedureIsValid(procedure)) \
  119.         elog(WARN, "index_%s: invalid %s regproc", \
  120.          CppAsString(x), CppAsString(y))
  121.  
  122. #define GET_SCAN_PROCEDURE(x,y) \
  123.     CppConcat(procedure = scan->relation->rd_am->,y); \
  124.     if (! RegProcedureIsValid(procedure)) \
  125.         elog(WARN, "index_%s: invalid %s regproc", \
  126.          CppAsString(x), CppAsString(y))
  127.  
  128.  
  129. /* ----------------------------------------------------------------
  130.  *           index_ interface functions
  131.  * ----------------------------------------------------------------
  132.  */
  133. /* ----------------
  134.  *    index_open - open an index relation by relationId
  135.  *
  136.  *    presently the relcache routines do all the work we need
  137.  *    to open/close index relations.
  138.  * ----------------
  139.  */
  140. Relation
  141. index_open(relationId)
  142.     ObjectId    relationId;
  143. {
  144.     return (Relation)
  145.     RelationIdGetRelation(relationId);
  146. }
  147.  
  148. /* ----------------
  149.  *    index_openr - open a index relation by name
  150.  *
  151.  *    presently the relcache routines do all the work we need
  152.  *    to open/close index relations.
  153.  * ----------------
  154.  */
  155. Relation
  156. index_openr(relationName)
  157.     Name relationName;
  158. {
  159.     return (Relation)
  160.     RelationNameGetRelation(relationName);
  161. }
  162.  
  163. /* ----------------
  164.  *    index_close - close a index relation
  165.  *
  166.  *    presently the relcache routines do all the work we need
  167.  *    to open/close index relations.
  168.  * ----------------
  169.  */
  170. void
  171. index_close(relation)
  172.     Relation relation;
  173. {
  174.     (void) RelationClose(relation);
  175. }
  176.  
  177. /* ----------------
  178.  *    index_insert - insert an index tuple into a relation
  179.  * ----------------
  180.  */
  181. GeneralInsertIndexResult
  182. index_insert(relation, indexTuple, offsetOutP)
  183.     Relation    relation;
  184.     IndexTuple    indexTuple;
  185.     double    *offsetOutP;
  186. {
  187.     RegProcedure        procedure;
  188.     InsertIndexResult        specificResult;
  189.     GeneralInsertIndexResult    returnResult;
  190.  
  191.     RELATION_CHECKS;
  192.     GET_REL_PROCEDURE(insert,aminsert);
  193.     
  194.     /* ----------------
  195.      *    have the am's insert proc do all the work.  
  196.      * ----------------
  197.      */
  198.     specificResult = (InsertIndexResult)
  199.     fmgr(procedure, relation, indexTuple, NULL);
  200.  
  201.     /* ----------------
  202.      *    the insert proc is supposed to return a "specific result" and
  203.      *  this routine has to return a "general result" so after we get
  204.      *  something back from the insert proc, we allocate a
  205.      *  "general result" and copy some crap between the two.
  206.      *
  207.      *  As far as I'm concerned all this result shit is needlessly c
  208.      *  omplicated and should be eliminated.  -cim 1/19/91
  209.      *
  210.      *  mao concurs.  regardless of how we feel here, however, it is
  211.      *  important to free memory we don't intend to return to anyone.
  212.      *  2/28/91
  213.      * ----------------
  214.      */
  215.     returnResult = (GeneralInsertIndexResult) palloc(sizeof *returnResult);
  216.     returnResult->pointerData = specificResult->pointerData;
  217.  
  218.     if (PointerIsValid(offsetOutP))
  219.     *offsetOutP = specificResult->offset;
  220.     
  221.     pfree(specificResult);
  222.     return (returnResult);
  223. }
  224.  
  225. /* ----------------
  226.  *    index_delete - delete an item from an index relation
  227.  * ----------------
  228.  */
  229. void
  230. index_delete(relation, indexItem)
  231.     Relation    relation;
  232.     ItemPointer    indexItem;
  233. {
  234.     RegProcedure    procedure;
  235.     
  236.     RELATION_CHECKS;
  237.     GET_REL_PROCEDURE(delete,amdelete);
  238.     
  239.     (void) fmgr(procedure, relation, indexItem);    
  240. }
  241.  
  242. /* ----------------
  243.  *    index_beginscan - start a scan of an index
  244.  * ----------------
  245.  */
  246. IndexScanDesc
  247. index_beginscan(relation, scanFromEnd, numberOfKeys, key)
  248.     Relation    relation;
  249.     Boolean    scanFromEnd;
  250.     uint16    numberOfKeys;
  251.     ScanKey    key;
  252. {
  253.     IndexScanDesc    scandesc;
  254.     RegProcedure    procedure;
  255.     
  256.     RELATION_CHECKS;
  257.     GET_REL_PROCEDURE(beginscan,ambeginscan);
  258.     
  259.     RelationSetRIntentLock(relation);
  260.  
  261.     scandesc = (IndexScanDesc)
  262.     fmgr(procedure, relation, scanFromEnd, numberOfKeys, key);
  263.     
  264.     return scandesc;
  265. }
  266.  
  267. /* ----------------
  268.  *    index_rescan  - restart a scan of an index
  269.  * ----------------
  270.  */
  271. void
  272. index_rescan(scan, scanFromEnd, key)
  273.     IndexScanDesc    scan;
  274.     bool        scanFromEnd;
  275.     ScanKey        key;
  276. {
  277.     RegProcedure    procedure;
  278.     
  279.     SCAN_CHECKS;
  280.     GET_SCAN_PROCEDURE(rescan,amrescan);
  281.  
  282.     (void) fmgr(procedure, scan, scanFromEnd, key);
  283. }
  284.  
  285. /* ----------------
  286.  *    index_endscan - end a scan
  287.  * ----------------
  288.  */
  289. void
  290. index_endscan(scan)
  291.     IndexScanDesc    scan;
  292. {
  293.     RegProcedure    procedure;
  294.     
  295.     SCAN_CHECKS;
  296.     GET_SCAN_PROCEDURE(endscan,amendscan);
  297.  
  298.     (void) fmgr(procedure, scan);
  299.  
  300.     RelationUnsetRIntentLock(scan->relation);
  301. }
  302.  
  303. /* ----------------
  304.  *    index_markpos  - mark a scan position
  305.  * ----------------
  306.  */
  307. void
  308. index_markpos(scan)
  309.     IndexScanDesc    scan;
  310. {
  311.     RegProcedure    procedure;
  312.     
  313.     SCAN_CHECKS;
  314.     GET_SCAN_PROCEDURE(markpos,ammarkpos);
  315.  
  316.     (void) fmgr(procedure, scan);
  317. }
  318.  
  319. /* ----------------
  320.  *    index_restrpos  - restore a scan position
  321.  * ----------------
  322.  */
  323. void
  324. index_restrpos(scan)
  325.     IndexScanDesc    scan;
  326. {
  327.     RegProcedure    procedure;
  328.     
  329.     SCAN_CHECKS;
  330.     GET_SCAN_PROCEDURE(restrpos,amrestrpos);
  331.  
  332.     (void) fmgr(procedure, scan);
  333. }
  334.  
  335. /* ----------------
  336.  *    index_getnext - get the next tuple from a scan
  337.  *
  338.  *      A RetrieveIndexResult is a index tuple/heap tuple pair
  339.  * ----------------
  340.  */
  341. RetrieveIndexResult
  342. index_getnext(scan, direction)
  343.     IndexScanDesc    scan;
  344.     ScanDirection    direction;
  345. {
  346.     RegProcedure        procedure;
  347.     RetrieveIndexResult        result;
  348.  
  349.     SCAN_CHECKS;
  350.     GET_SCAN_PROCEDURE(getnext,amgettuple);
  351.  
  352.     /* ----------------
  353.      *    have the am's gettuple proc do all the work.  
  354.      * ----------------
  355.      */
  356.     result = (RetrieveIndexResult)
  357.     fmgr(procedure, scan, direction);
  358.  
  359.     if (! RetrieveIndexResultIsValid(result))
  360.     return NULL;
  361.     
  362.     return result;
  363. }
  364. /* ----------------
  365.  *    index_getprocid
  366.  *
  367.  *    Some indexed access methods may require support routines that are
  368.  *    not in the operator class/operator model imposed by pg_am.  These
  369.  *    access methods may store the OIDs of registered procedures they
  370.  *    need in pg_amproc.  These registered procedure OIDs are ordered in
  371.  *    a way that makes sense to the access method, and used only by the
  372.  *    access method.  The general index code doesn't know anything about
  373.  *    the routines involved; it just builds an ordered list of them for
  374.  *    each attribute on which an index is defined.
  375.  *
  376.  *    This routine returns the requested procedure OID for a particular
  377.  *    indexed attribute.
  378.  * ----------------
  379.  */
  380.  
  381. RegProcedure
  382. index_getprocid(irel, attnum, procnum)
  383.     Relation irel;
  384.     AttributeNumber attnum;
  385.     uint16 procnum;
  386. {
  387.     RegProcedure *loc;
  388.     AttributeNumber natts;
  389.  
  390.     natts = irel->rd_rel->relnatts;
  391.  
  392.     loc = *((RegProcedure **)
  393.        (((char *) &(irel->rd_att.data[natts])) + sizeof(IndexStrategy)));
  394.  
  395.     Assert(loc != NULL);
  396.  
  397.     return (loc[(natts * (procnum - 1)) + (attnum - 1)]);
  398. }
  399.  
  400. /* ----------------
  401.  *    InsertIndexTuple
  402.  * ----------------
  403.  */
  404. void
  405. InsertIndexTuple(heapRelation, indexRelation, numberOfAttributes, 
  406.          attributeNumber, heapTuple, 
  407.          indexStrategy, parameterCount, parameter)
  408.     Relation        heapRelation;
  409.     Relation        indexRelation;
  410.     AttributeNumber    numberOfAttributes;
  411.     AttributeNumber    attributeNumber[];
  412.     HeapTuple              heapTuple;
  413.     IndexStrategy    indexStrategy;
  414.     uint16        parameterCount;
  415.     Datum        parameter[];
  416. {
  417.     HeapScanDesc    scan;
  418.     Buffer        buffer;
  419.     AttributeNumber    attributeIndex;
  420.     IndexTuple        indexTuple;
  421.     TupleDescriptor    heapDescriptor;
  422.     TupleDescriptor    indexDescriptor;
  423.     Datum        *datum;
  424.     Boolean        *nullv;
  425.  
  426.     char        *dom[2];
  427.     extern        HasCached;
  428.     extern char        CachedClass[];
  429.     extern        fillCached();
  430.     GeneralInsertIndexResult    insertResult;
  431.  
  432.     /* more & better checking is needed */
  433.     Assert(ObjectIdIsValid(indexRelation->rd_rel->relam));    /* XXX */
  434.  
  435.     datum = (Datum *)   palloc(numberOfAttributes * sizeof *datum);
  436.     nullv =  (Boolean *) palloc(numberOfAttributes * sizeof *nullv);
  437.     
  438.     heapDescriptor =  RelationGetTupleDescriptor(heapRelation);
  439.     indexDescriptor = RelationGetTupleDescriptor(indexRelation);
  440.  
  441.     Assert(HeapTupleIsValid(heapTuple));
  442.     for (attributeIndex = 1; attributeIndex <= numberOfAttributes;
  443.      attributeIndex += 1) {
  444.       
  445.     AttributeOffset    attributeOffset;
  446.     Boolean        attributeIsNull;
  447.       
  448.     attributeOffset = AttributeNumberGetAttributeOffset(attributeIndex);
  449.  
  450.     datum[attributeOffset] =
  451.         PointerGetDatum( heap_getattr(heapTuple, buffer,
  452.                       attributeNumber[attributeOffset],
  453.                       heapDescriptor, &attributeIsNull) );
  454.     
  455.       nullv[attributeOffset] = (attributeIsNull) ? 'n' : ' ';
  456.     }
  457.  
  458.     indexTuple = (IndexTuple)
  459.     index_formtuple(numberOfAttributes,
  460.             indexDescriptor,
  461.             datum,
  462.             nullv);
  463.  
  464.     indexTuple->t_tid = heapTuple->t_ctid;
  465.  
  466.     insertResult = index_insert(indexRelation, indexTuple, (double *) 0);
  467.     
  468.     pfree(indexTuple);
  469.     pfree(nullv);
  470.     pfree(datum);
  471. }
  472.  
  473. /* ----------------
  474.  *    GetHeapTuple
  475.  * ----------------
  476.  */
  477. HeapTuple
  478. GetHeapTuple(result, heaprel, buffer)
  479.     GeneralRetrieveIndexResult      result;
  480.     Relation                        heaprel;
  481.     Buffer                          buffer;
  482. {
  483.     ItemPointer     pointer;
  484.     HeapTuple       tuple;
  485.  
  486.     Assert(GeneralRetrieveIndexResultIsValid(result));
  487.  
  488.     pointer = GeneralRetrieveIndexResultGetHeapItemPointer(result);
  489.  
  490.     if (! ItemPointerIsValid(pointer))
  491.     return NULL;
  492.  
  493.     tuple = heap_fetch(heaprel, NowTimeQual, pointer, &buffer);
  494.  
  495.     if (! HeapTupleIsValid(tuple)) 
  496.     return(NULL);
  497.     else 
  498.     return(tuple);
  499. }
  500.  
  501. Datum
  502. GetIndexValue(tuple, hTupDesc, attOff, attrNums, fInfo, attNull, buffer)
  503.     HeapTuple tuple;
  504.     TupleDescriptor hTupDesc;
  505.     AttributeOffset attOff;
  506.     AttributeNumber attrNums[];
  507.     FuncIndexInfo *fInfo;
  508.     Boolean *attNull;
  509.     Buffer buffer;
  510. {
  511.     Datum returnVal;
  512.  
  513.     if (PointerIsValid(fInfo) && FIgetProcOid(fInfo) != InvalidObjectId)
  514.     {
  515.     int i;
  516.     Datum *attData = (Datum *)palloc(FIgetnArgs(fInfo)*sizeof(Datum));
  517.  
  518.     for (i = 0; i < FIgetnArgs(fInfo); i++)
  519.     {
  520.         attData[i] = (Datum) heap_getattr(tuple, buffer, attrNums[i], 
  521.                           hTupDesc, attNull);
  522.     }
  523.     returnVal = (Datum)fmgr_array_args(FIgetProcOid(fInfo),
  524.                        FIgetnArgs(fInfo),
  525.                        attData);
  526.     pfree(attData);
  527.     *attNull = FALSE;
  528.     }
  529.     else
  530.     {
  531.     returnVal = (Datum) heap_getattr(tuple, buffer, attrNums[attOff], 
  532.                      hTupDesc, attNull);
  533.     }
  534.     return returnVal;
  535. }
  536.